﻿using Smile.Mvvm.Model;
using Smile.Threading;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Smile.Network.Http
{
    public class RemoteResource : ModelBase
    {
        // @Properties
        /// <summary>Gets or sets the size of the image.</summary>
        ///
        /// <value>The image size.</value>
        public int Size
        {
            get
            {
                return _size;
            }
            private set
            {
                if (_size != value)
                {
                    _size = value;
                    RaisePropertyChanged();
                }
            }
        }

        /// <summary>Gets or sets the size already downloaded.</summary>
        ///
        /// <value>The size already downloaded.</value>
        public int DownloadedSize
        {
            get
            {
                return _downloadedSize;
            }
            private set
            {
                if (_downloadedSize != value)
                {
                    _downloadedSize = value;
                    RaisePropertyChanged();
                }
            }
        }

        /// <summary>Gets or sets the download progress.</summary>
        ///
        /// <value>The download progress.</value>
        public int DownloadProgress
        {
            get
            {
                return _downloadProgress;
            }
            private set
            {
                if (_downloadProgress != value)
                {
                    _downloadProgress = value;
                    RaisePropertyChanged();
                }
            }
        }

        /// <summary>Gets or sets a value indicating whether the image is downloaded.</summary>
        ///
        /// <value>true if the image is downloaded, false if not.</value>
        public bool IsDownloaded
        {
            get
            {
                return _isDownloaded;
            }
            private set
            {
                if (_isDownloaded != value)
                {
                    _isDownloaded = value;
                    RaisePropertyChanged();
                }
            }
        }

        /// <summary>Gets or sets URI of the image.</summary>
        ///
        /// <value>The URI.</value>
        public Uri Uri
        {
            get
            {
                return _uri;
            }
            set
            {
                if (_uri != value)
                {
                    _uri = value;
                    RaisePropertyChanged();
                    Data = null;
                    Size = 0;
                    DownloadedSize = 0;
                    DownloadProgress = 0;
                    IsDownloaded = false;
                }
            }
        }

        /// <summary>Gets or sets the data of the resource.</summary>
        ///
        /// <value>The data of the image.</value>
        public byte[] Data
        {
            get
            {
                return _data;
            }
            private set
            {
                if (_data != value)
                {
                    _data = value;
                    RaisePropertyChanged();
                }
            }
        }


        // @Public
        /// <summary>Default constructor.</summary>
        public RemoteResource()
        {
        }

        /// <summary>Constructor.</summary>
        ///
        /// <param name="uri">The URI.</param>
        public RemoteResource(Uri uri)
        {
            Uri = uri;
        }

        /// <summary>Downloads the image if it's not yet done (Awaitable).</summary>
        ///
        /// <returns>true if the image is downloaded, false if not.</returns>
        public async Task<bool> DownloadAsync()
        {
            if (IsDownloaded)
            {
                return true;
            }
            else if (Uri != null)
            {
                ++_downloadTry;
                var request = new HttpDownloader();
                request.DownloadProgressChanged += DownloadImageProgressChanged;
                var response = await request.DownloadAsync(Uri);

                if (response.Status == HttpStatusCode.OK)
                {
                    Data = response.ContentBytes;
                    IsDownloaded = true;
                    _downloadTry = 0;
                    return true;
                }
                else if (_downloadTry < 3)
                {
                    return await DownloadAsync();
                }
            }
            return false;
        }

        
        // @Private
        int             _size = 0;
        int             _downloadedSize = 0;
        int             _downloadProgress = 0;
        int             _downloadTry = 0;
        bool            _isDownloaded = false;
        Uri             _uri = null;
        byte[]          _data;


        void DownloadImageProgressChanged(object sender, DownloadInfo downloadInfo)
        {
            Dispatcher.BeginInvoke(() =>
                {
                    Size = downloadInfo.Size;
                    DownloadedSize = downloadInfo.Downloaded;
                    DownloadProgress = downloadInfo.Progress;
                });
        }
    }
}
